package com.lanyou.cook.web;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.joda.time.DateTime;
import org.joda.time.Hours;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.datadictionary.InterfaceRunResult;
import com.lanyou.cook.entity.domain.InterfaceExecutionResult;
import com.lanyou.cook.entity.domain.SystemInterface;
import com.lanyou.cook.repository.SystemInterfaceRepository;
import com.lanyou.cook.util.gson.GsonUtil;

/**
 * 领域服务相关业务控制层
 * @author 杨晨睿
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/fieldServiceMonitor")
public class FieldServiceMonitorController {

	@PersistenceContext
	private EntityManager entityManager;

	@Autowired
	private SystemInterfaceRepository systemInterfaceRepository;

	private static FastDateFormat fastDateFormat1 = FastDateFormat.getInstance(Constants.DATETIME_PATTERN_1);

	/**
	 * 统计所属领域下作业数
	 * @param fieldName 类型:String 待查询的领域名称
	 * @return 类型:String 返回的作业数据
	 */
	@RequestMapping(value = "/search/countByFieldNameAndTime", produces = "application/json")
	@RequiresPermissions(value={"fieldServiceMonitoring:view"})
	public String countByFieldIdAndTime(String fieldName) throws ParseException {

		List<SystemInterface> systemInterfaces = systemInterfaceRepository.findByOwnerFieldSystem_Field_Name(fieldName);
		List<String> systemInterfaceIds = new ArrayList<String>();
		for (SystemInterface systemInterface : systemInterfaces) {
			systemInterfaceIds.add(systemInterface.getId());
		}

		Date now = new Date();
		
		Date beginOfRunEndTime = DateUtils.truncate(now, Calendar.DAY_OF_MONTH);
		//String b1 = fastDateFormat1.format(beginOfRunEndTime);
		
		Date endOfRunEndTime = DateUtils.ceiling(now, Calendar.DAY_OF_MONTH);
		//String b2 = fastDateFormat1.format(endOfRunEndTime);

		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery();

		// 构建FROM和JOIN部分
		Root<InterfaceExecutionResult> rootInterfaceExecutionResult = cq.from(InterfaceExecutionResult.class);

		// 构建WHERE部分
		List<Predicate> predicatesList = new ArrayList<>();
		if (StringUtils.isNotBlank(fieldName)) {
			predicatesList.add(cb.equal(rootInterfaceExecutionResult.get("fieldName"), fieldName));
		}

		predicatesList
				.add(cb.between(rootInterfaceExecutionResult.get("runBeginTime"), beginOfRunEndTime, endOfRunEndTime));
		cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

		// 构建GROUP BY部分
		// cq.groupBy(rootInterfaceExecutionResult.get("runResult"));

		// 构建SELECT部分
		cq.multiselect(rootInterfaceExecutionResult.get("fieldName").alias("fieldName"),
				rootInterfaceExecutionResult.get("runResult").alias("runResult"),
				rootInterfaceExecutionResult.get("runBeginTime").alias("runBeginTime"));

		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();

		// 按整点来统计运行时长
		Map<Date, JsonObject> totalInterfaces = new HashMap<>();

		for (Tuple tuple : queryResult) {
			JsonObject interfaceJson = new JsonObject();
			Date runBeginTime = tuple.get("runBeginTime", Date.class);
			runBeginTime = DateUtils.ceiling(runBeginTime, Calendar.HOUR_OF_DAY);

			JsonObject totalInterfaceHour = totalInterfaces.get(runBeginTime);

			if (totalInterfaceHour == null) {

				if (StringUtils.equals(tuple.get("runResult", String.class), InterfaceRunResult.Faild.ValueCode)) {
					interfaceJson.addProperty("faildRunInterface", 1);
					interfaceJson.addProperty("practicalRunInterface", 1);
				}
				if (StringUtils.equals(tuple.get("runResult", String.class), InterfaceRunResult.Success.ValueCode)) {
					interfaceJson.addProperty("faildRunInterface", 0);
					interfaceJson.addProperty("practicalRunInterface", 1);
				}
			} else {

				if (StringUtils.equals(tuple.get("runResult", String.class), InterfaceRunResult.Faild.ValueCode)) {
					interfaceJson.addProperty("faildRunInterface",
							GsonUtil.getInt(totalInterfaceHour, "faildRunInterface", 0) + 1);
					interfaceJson.addProperty("practicalRunInterface",
							GsonUtil.getInt(totalInterfaceHour, "practicalRunInterface", 0) + 1);
				}
				if (StringUtils.equals(tuple.get("runResult", String.class), InterfaceRunResult.Success.ValueCode)) {
					interfaceJson.addProperty("faildRunInterface",
							GsonUtil.getInt(totalInterfaceHour, "faildRunInterface", 0));
					interfaceJson.addProperty("practicalRunInterface",
							GsonUtil.getInt(totalInterfaceHour, "practicalRunInterface", 0) + 1);
				}
			}
			totalInterfaces.put(runBeginTime, interfaceJson);
		}

		JsonArray jsonDatas = new JsonArray();
		// 修正时间点，使结果的数量刚好等于统计时间段内的小时数
		Hours hoursBetween = Hours.hoursBetween(new DateTime(beginOfRunEndTime), new DateTime(endOfRunEndTime));
		Date timePoint = DateUtils.ceiling(beginOfRunEndTime, Calendar.HOUR);
		for (int i = 1; i <= hoursBetween.getHours(); i += 1) {
			
			//TODO: 统计未来时间段的应运行数量
//			Long interfaceNumber = kettleJobScheduler.getTotalFireAmount(systemInterfaceIds, beginOfRunEndTime,
//					DateUtils.addHours(beginOfRunEndTime, 1));
			long interfaceNumber = 0;
			JsonObject totalInterfaceHour = totalInterfaces.get(timePoint);
			if (totalInterfaceHour == null) {
				totalInterfaceHour = new JsonObject();
				totalInterfaceHour.addProperty("faildRunInterface", 0);
				totalInterfaceHour.addProperty("practicalRunInterface", 0);
			}

			JsonObject jo = new JsonObject();
			jo.addProperty("time", fastDateFormat1.format(timePoint));
			totalInterfaceHour.addProperty("shouldRunInterface", interfaceNumber);
			jo.addProperty("interfaceJson", totalInterfaceHour.toString());
			jsonDatas.add(jo);

			timePoint = DateUtils.addHours(timePoint, 1);
		}

		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();

	}

}
